/** layui-v2.5.7 自定义模块-工具模块 */
layui.define(function(exports){
	//自定义模块的对象
	var _ = {};
	var types = _.types = (function (exports) {
			/* Used for typescript definitions only.
			 */

			/* typescript
			 * export declare namespace types {
			 *     interface Collection<T> {}
			 *     interface List<T> extends Collection<T> {
			 *         [index: number]: T;
			 *         length: number;
			 *     }
			 *     interface ListIterator<T, TResult> {
			 *         (value: T, index: number, list: List<T>): TResult;
			 *     }
			 *     interface Dictionary<T> extends Collection<T> {
			 *         [index: string]: T;
			 *     }
			 *     interface ObjectIterator<T, TResult> {
			 *         (element: T, key: string, list: Dictionary<T>): TResult;
			 *     }
			 *     interface MemoIterator<T, TResult> {
			 *         (prev: TResult, curr: T, index: number, list: List<T>): TResult;
			 *     }
			 *     interface MemoObjectIterator<T, TResult> {
			 *         (prev: TResult, curr: T, key: string, list: Dictionary<T>): TResult;
			 *     }
			 *     type Fn<T> = (...args: any[]) => T;
			 *     type AnyFn = Fn<any>;
			 *     type PlainObj<T> = { [name: string]: T };
			 * }
			 * export declare const types: {};
			 */
			exports = {};
			return exports;
	})({});
	var has = _.has = (function (exports) {
			/* Checks if key is a direct property.
			 *
			 * |Name  |Desc                            |
			 * |------|--------------------------------|
			 * |obj   |Object to query                 |
			 * |key   |Path to check                   |
			 * |return|True if key is a direct property|
			 */
			/* has({ one: 1 }, 'one'); // -> true */
			var hasOwnProp = Object.prototype.hasOwnProperty;
			exports = function(obj, key) {
					return hasOwnProp.call(obj, key);
			};
			return exports;
	})({});
	var slice = _.slice = (function (exports) {
			/* Create slice of source array or array-like object.
			 *
			 * |Name            |Desc                      |
			 * |----------------|--------------------------|
			 * |array           |Array to slice            |
			 * |start=0         |Start position            |
			 * |end=array.length|End position, not included|
			 */
			/* example
			 * slice([1, 2, 3, 4], 1, 2); // -> [2]
			 */
			exports = function(arr, start, end) {
					var len = arr.length;

					if (start == null) {
							start = 0;
					} else if (start < 0) {
							start = Math.max(len + start, 0);
					} else {
							start = Math.min(start, len);
					}
					if (end == null) {
							end = len;
					} else if (end < 0) {
							end = Math.max(len + end, 0);
					} else {
							end = Math.min(end, len);
					}
					var ret = [];
					while (start < end) {
							ret.push(arr[start++]);
					}
					return ret;
			};
			return exports;
	})({});
	var keys = _.keys = (function (exports) {
			/* Create an array of the own enumerable property names of object.
			 *
			 * |Name  |Desc                   |
			 * |------|-----------------------|
			 * |obj   |Object to query        |
			 * |return|Array of property names|
			 */
			/* example
			 * keys({ a: 1 }); // -> ['a']
			 */
			if (Object.keys && !false) {
					exports = Object.keys;
			} else {
					exports = function(obj) {
							var ret = [];

							for (var key in obj) {
									if (has(obj, key)) ret.push(key);
							}
							return ret;
					};
			}
			return exports;
	})({});
	var before = _.before = (function (exports) {
			/* Create a function that invokes less than n times.
			 *
			 * |Name  |Desc                                            |
			 * |------|------------------------------------------------|
			 * |n     |Number of calls at which fn is no longer invoked|
			 * |fn    |Function to restrict                            |
			 * |return|New restricted function                         |
			 *
			 * Subsequent calls to the created function return the result of the last fn invocation.
			 */
			/* example
			 * const fn = before(5, function() {});
			 * fn(); // Allow function to be call 4 times at last.
			 */
			exports = function(n, fn) {
					var memo;
					return function() {
							if (--n > 0) memo = fn.apply(this, arguments);
							if (n <= 1) fn = null;
							return memo;
					};
			};
			return exports;
	})({});
	var isObj = _.isObj = (function (exports) {
			/* Check if value is the language type of Object.
			 *
			 * |Name  |Desc                      |
			 * |------|--------------------------|
			 * |val   |Value to check            |
			 * |return|True if value is an object|
			 *
			 * [Language Spec](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types)
			 */
			/* example
			 * isObj({}); // -> true
			 * isObj([]); // -> true
			 */
			exports = function(val) {
					var type = typeof val;
					return !!val && (type === 'function' || type === 'object');
			};
			return exports;
	})({});
	var create = _.create = (function (exports) {
			/* Create new object using given object as prototype.
			 *
			 * |Name  |Desc                   |
			 * |------|-----------------------|
			 * |proto |Prototype of new object|
			 * |return|Created object         |
			 */
			/* example
			 * const obj = create({ a: 1 });
			 * console.log(obj.a); // -> 1
			 */
			exports = function(proto) {
					if (!isObj(proto)) return {};
					if (objCreate && !false) return objCreate(proto);
					function noop() {}
					noop.prototype = proto;
					return new noop();
			};
			var objCreate = Object.create;
			return exports;
	})({});
	var inherits = _.inherits = (function (exports) {
			/* Inherit the prototype methods from one constructor into another.
			 *
			 * |Name      |Desc       |
			 * |----------|-----------|
			 * |Class     |Child Class|
			 * |SuperClass|Super Class|
			 */
			/* example
			 * function People(name) {
			 *     this._name = name;
			 * }
			 * People.prototype = {
			 *     getName: function() {
			 *         return this._name;
			 *     }
			 * };
			 * function Student(name) {
			 *     this._name = name;
			 * }
			 * inherits(Student, People);
			 * const s = new Student('RedHood');
			 * s.getName(); // -> 'RedHood'
			 */
			exports = function(Class, SuperClass) {
					Class.prototype = create(SuperClass.prototype);
			};
			return exports;
	})({});
	var isUndef = _.isUndef = (function (exports) {
			/* Check if value is undefined.
			 *
			 * |Name  |Desc                      |
			 * |------|--------------------------|
			 * |val   |Value to check            |
			 * |return|True if value is undefined|
			 */
			/* example
			 * isUndef(void 0); // -> true
			 * isUndef(null); // -> false
			 */
			exports = function(val) {
					return val === void 0;
			};
			return exports;
	})({});
	var optimizeCb = _.optimizeCb = (function (exports) {
			/* Used for function context binding.
			 */
			exports = function(fn, ctx, argCount) {
					if (isUndef(ctx)) return fn;
					switch (argCount == null ? 3 : argCount) {
							case 1:
									return function(val) {
											return fn.call(ctx, val);
									};
							case 3:
									return function(val, idx, collection) {
											return fn.call(ctx, val, idx, collection);
									};
							case 4:
									return function(accumulator, val, idx, collection) {
											return fn.call(ctx, accumulator, val, idx, collection);
									};
					}
					return function() {
							return fn.apply(ctx, arguments);
					};
			};
			return exports;
	})({});
	var identity = _.identity = (function (exports) {
			/* Return the first argument given.
			 *
			 * |Name  |Desc       |
			 * |------|-----------|
			 * |val   |Any value  |
			 * |return|Given value|
			 */
			/* example
			 * identity('a'); // -> 'a'
			 */
			exports = function(val) {
					return val;
			};
			return exports;
	})({});
	_.isAbsoluteUrl = (function (exports) {
			/* Check if an url is absolute.
			 *
			 * |Name  |Desc                   |
			 * |------|-----------------------|
			 * |url   |Url to check           |
			 * |return|True if url is absolute|
			 */
			/* example
			 * isAbsoluteUrl('http://www.surunzi.com'); // -> true
			 * isAbsoluteUrl('//www.surunzi.com'); // -> false
			 * isAbsoluteUrl('surunzi.com'); // -> false
			 */
			exports = function(url) {
					return regAbsolute.test(url);
			};
			var regAbsolute = /^[a-z][a-z0-9+.-]*:/;
			return exports;
	})({});
	var objToStr = _.objToStr = (function (exports) {
			/* Alias of Object.prototype.toString.
			 *
			 * |Name  |Desc                                |
			 * |------|------------------------------------|
			 * |val   |Source value                        |
			 * |return|String representation of given value|
			 */
			/* example
			 * objToStr(5); // -> '[object Number]'
			 */
			var ObjToStr = Object.prototype.toString;
			exports = function(val) {
					return ObjToStr.call(val);
			};
			return exports;
	})({});
	var isArgs = _.isArgs = (function (exports) {
			/* Check if value is classified as an arguments object.
			 *
			 * |Name  |Desc                                |
			 * |------|------------------------------------|
			 * |val   |Value to check                      |
			 * |return|True if value is an arguments object|
			 */
			/* example
			 * isArgs(
			 *     (function() {
			 *         return arguments;
			 *     })()
			 * ); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object Arguments]';
			};
			return exports;
	})({});
	var isArr = _.isArr = (function (exports) {
			/* Check if value is an `Array` object.
			 *
			 * |Name  |Desc                              |
			 * |------|----------------------------------|
			 * |val   |Value to check                    |
			 * |return|True if value is an `Array` object|
			 */
			/* example
			 * isArr([]); // -> true
			 * isArr({}); // -> false
			 */
			if (Array.isArray && !false) {
					exports = Array.isArray;
			} else {
					exports = function(val) {
							return objToStr(val) === '[object Array]';
					};
			}
			return exports;
	})({});
	var castPath = _.castPath = (function (exports) {
			/* Cast value into a property path array.
			 *
			 * |Name  |Desc               |
			 * |------|-------------------|
			 * |path  |Value to inspect   |
			 * |obj   |Object to query    |
			 * |return|Property path array|
			 */
			/* example
			 * castPath('a.b.c'); // -> ['a', 'b', 'c']
			 * castPath(['a']); // -> ['a']
			 * castPath('a[0].b'); // -> ['a', '0', 'b']
			 * castPath('a.b.c', { 'a.b.c': true }); // -> ['a.b.c']
			 */
			exports = function(str, obj) {
					if (isArr(str)) return str;
					if (obj && has(obj, str)) return [str];
					var ret = [];
					str.replace(regPropName, function(match, number, quote, str) {
							ret.push(quote ? str.replace(regEscapeChar, '$1') : number || match);
					});
					return ret;
			}; // Lodash _stringToPath
			var regPropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
			var regEscapeChar = /\\(\\)?/g;
			return exports;
	})({});
	var safeGet = _.safeGet = (function (exports) {
			/* Get object property, don't throw undefined error.
			 *
			 * |Name  |Desc                     |
			 * |------|-------------------------|
			 * |obj   |Object to query          |
			 * |path  |Path of property to get  |
			 * |return|Target value or undefined|
			 */
			/* example
			 * const obj = { a: { aa: { aaa: 1 } } };
			 * safeGet(obj, 'a.aa.aaa'); // -> 1
			 * safeGet(obj, ['a', 'aa']); // -> {aaa: 1}
			 * safeGet(obj, 'a.b'); // -> undefined
			 */
			exports = function(obj, path) {
					path = castPath(path, obj);
					var prop;
					prop = path.shift();
					while (!isUndef(prop)) {
							obj = obj[prop];
							if (obj == null) return;
							prop = path.shift();
					}
					return obj;
			};
			return exports;
	})({});
	var isFn = _.isFn = (function (exports) {
			/* Check if value is a function.
			 *
			 * |Name  |Desc                       |
			 * |------|---------------------------|
			 * |val   |Value to check             |
			 * |return|True if value is a function|
			 *
			 * Generator function is also classified as true.
			 */
			/* example
			 * isFn(function() {}); // -> true
			 * isFn(function*() {}); // -> true
			 * isFn(async function() {}); // -> true
			 */
			exports = function(val) {
					var objStr = objToStr(val);
					return (
							objStr === '[object Function]' ||
							objStr === '[object GeneratorFunction]' ||
							objStr === '[object AsyncFunction]'
					);
			};
			return exports;
	})({});
	var getProto = _.getProto = (function (exports) {
			/* Get prototype of an object.
			 *
			 * |Name  |Desc                                         |
			 * |------|---------------------------------------------|
			 * |obj   |Target object                                |
			 * |return|Prototype of given object, null if not exists|
			 */
			/* example
			 * const a = {};
			 * getProto(Object.create(a)); // -> a
			 */
			var getPrototypeOf = Object.getPrototypeOf;
			var ObjectCtr = {}.constructor;
			exports = function(obj) {
					if (!isObj(obj)) return;
					if (getPrototypeOf && !false) return getPrototypeOf(obj);
					var proto = obj.__proto__;
					if (proto || proto === null) return proto;
					if (isFn(obj.constructor)) return obj.constructor.prototype;
					if (obj instanceof ObjectCtr) return ObjectCtr.prototype;
			};
			return exports;
	})({});
	/* ------------------------------ isMiniProgram ------------------------------ */
	var isMiniProgram = _.isMiniProgram = (function (exports) {
			/* Check if running in wechat mini program.
			 */
			/* example
			 * console.log(isMiniProgram); // -> true if running in mini program.
			 */
			exports = typeof wx !== 'undefined' && isFn(wx.openLocation);
			return exports;
	})({});
	_.isArrBuffer = (function (exports) {
			/* Check if value is an ArrayBuffer.
			 *
			 * |Name  |Desc                           |
			 * |------|-------------------------------|
			 * |val   |Value to check                 |
			 * |return|True if value is an ArrayBuffer|
			 */
			/* example
			 * isArrBuffer(new ArrayBuffer(8)); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object ArrayBuffer]';
			};
			return exports;
	})({});
	var isNum = _.isNum = (function (exports) {
			/* Check if value is classified as a Number primitive or object.
			 *
			 * |Name  |Desc                                 |
			 * |------|-------------------------------------|
			 * |val   |Value to check                       |
			 * |return|True if value is correctly classified|
			 */

			/* example
			 * isNum(5); // -> true
			 * isNum(5.1); // -> true
			 * isNum({}); // -> false
			 */
			exports = function(val) {
					return objToStr(val) === '[object Number]';
			};
			return exports;
	})({});
	var isArrLike = _.isArrLike = (function (exports) {
			/* Check if value is array-like.
			 *
			 * |Name  |Desc                       |
			 * |------|---------------------------|
			 * |val   |Value to check             |
			 * |return|True if value is array like|
			 *
			 * Function returns false.
			 */
			/* example
			 * isArrLike('test'); // -> true
			 * isArrLike(document.body.children); // -> true;
			 * isArrLike([1, 2, 3]); // -> true
			 */
			var MAX_ARR_IDX = Math.pow(2, 53) - 1;
			exports = function(val) {
					if (!val) return false;
					var len = val.length;
					return isNum(len) && len >= 0 && len <= MAX_ARR_IDX && !isFn(val);
			};
			return exports;
	})({});
	var each = _.each = (function (exports) {
			/* Iterate over elements of collection and invokes iterator for each element.
			 *
			 * |Name    |Desc                          |
			 * |--------|------------------------------|
			 * |obj     |Collection to iterate over    |
			 * |iterator|Function invoked per iteration|
			 * |ctx     |Function context              |
			 */
			/* example
			 * each({ a: 1, b: 2 }, function(val, key) {});
			 */
			exports = function(obj, iterator, ctx) {
					iterator = optimizeCb(iterator, ctx);
					var i, len;

					if (isArrLike(obj)) {
							for (i = 0, len = obj.length; i < len; i++) {
									iterator(obj[i], i, obj);
							}
					} else {
							var _keys = keys(obj);

							for (i = 0, len = _keys.length; i < len; i++) {
									iterator(obj[_keys[i]], _keys[i], obj);
							}
					}
					return obj;
			};
			return exports;
	})({});
	var createAssigner = _.createAssigner = (function (exports) {
			/* Used to create extend, extendOwn and defaults.
			 *
			 * |Name    |Desc                          |
			 * |--------|------------------------------|
			 * |keysFn  |Function to get object keys   |
			 * |defaults|No override when set to true  |
			 * |return  |Result function, extend...    |
			 */
			exports = function(keysFn, defaults) {
					return function(obj) {
							each(arguments, function(src, idx) {
									if (idx === 0) return;
									var keys = keysFn(src);
									each(keys, function(key) {
											if (!defaults || isUndef(obj[key])) obj[key] = src[key];
									});
							});
							return obj;
					};
			};
			return exports;
	})({});
	var extendOwn = _.extendOwn = (function (exports) {
			/* Like extend, but only copies own properties over to the destination object.
			 *
			 * |Name       |Desc              |
			 * |-----------|------------------|
			 * |destination|Destination object|
			 * |...sources |Sources objects   |
			 * |return     |Destination object|
			 */
			/* example
			 * extendOwn({ name: 'RedHood' }, { age: 24 }); // -> {name: 'RedHood', age: 24}
			 */
			exports = createAssigner(keys);
			return exports;
	})({});
	_.isAsyncFn = (function (exports) {
			/* Check if value is an async function.
			 *
			 * |Name  |Desc                              |
			 * |------|----------------------------------|
			 * |val   |Value to check                    |
			 * |return|True if value is an async function|
			 */
			/* example
			 * isAsyncFn(function*() {}); // -> false
			 * isAsyncFn(function() {}); // -> false
			 * isAsyncFn(async function() {}); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object AsyncFunction]';
			};
			return exports;
	})({});
	_.isBlob = (function (exports) {
			/* Check if value is a Blob.
			 *
			 * |Name  |Desc                   |
			 * |------|-----------------------|
			 * |val   |Value to check         |
			 * |return|True if value is a Blob|
			 */
			/* example
			 * isBlob(new Blob([])); // -> true;
			 * isBlob([]); // -> false
			 */
			exports = function(val) {
					return objToStr(val) === '[object Blob]';
			};
			return exports;
	})({});
	_.isBool = (function (exports) {
			/* Check if value is a boolean primitive.
			 *
			 * |Name  |Desc                      |
			 * |------|--------------------------|
			 * |val   |Value to check            |
			 * |return|True if value is a boolean|
			 */
			/* example
			 * isBool(true); // -> true
			 * isBool(false); // -> true
			 * isBool(1); // -> false
			 */
			exports = function(val) {
					return val === true || val === false;
			};
			return exports;
	})({});
	var isBrowser = _.isBrowser = (function (exports) {
			/* Check if running in a browser.
			 */
			/* example
			 * console.log(isBrowser); // -> true if running in a browser
			 */
			exports =
					typeof window === 'object' &&
					typeof document === 'object' &&
					document.nodeType === 9;
			return exports;
	})({});
	_.isBuffer = (function (exports) {
			/* Check if value is a buffer.
			 *
			 * |Name  |Desc                     |
			 * |------|-------------------------|
			 * |val   |The value to check       |
			 * |return|True if value is a buffer|
			 */
			/* example
			 * isBuffer(new Buffer(4)); // -> true
			 */
			exports = function(val) {
					if (val == null) return false;
					if (val._isBuffer) return true;
					return (
							val.constructor &&
							isFn(val.constructor.isBuffer) &&
							val.constructor.isBuffer(val)
					);
			};
			return exports;
	})({});
	_.isClose = (function (exports) {
			/* Check if values are close(almost equal) to each other.
			 *
			 * `abs(a-b) <= max(relTol * max(abs(a), abs(b)), absTol)`
			 *
			 * |Name       |Desc                    |
			 * |-----------|------------------------|
			 * |a          |Number to compare       |
			 * |b          |Number to compare       |
			 * |relTol=1e-9|Relative tolerance      |
			 * |absTol=0   |Absolute tolerance      |
			 * |return     |True if values are close|
			 */
			/* example
			 * isClose(1, 1.0000000001); // -> true
			 * isClose(1, 2); // -> false
			 * isClose(1, 1.2, 0.3); // -> true
			 * isClose(1, 1.2, 0.1, 0.3); // -> true
			 */
			exports = function(a, b, relTol, absTol) {
					if (!isNum(relTol)) relTol = 1e-9;
					if (!isNum(absTol)) absTol = 0;
					return abs(a - b) <= max(relTol * max(abs(a), abs(b)), absTol);
			};
			var abs = Math.abs;
			var max = Math.max;
			return exports;
	})({});
	_.isDate = (function (exports) {
			/* Check if value is classified as a Date object.
			 *
			 * |Name  |Desc                          |
			 * |------|------------------------------|
			 * |val   |value to check                |
			 * |return|True if value is a Date object|
			 */
			/* example
			 * isDate(new Date()); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object Date]';
			};
			return exports;
	})({});
	var root = _.root = (function (exports) {
			/* Root object reference, `global` in nodeJs, `window` in browser. */
			exports = isBrowser ? window : global;
			return exports;
	})({});
	_.isEl = (function (exports) {
			/* Check if value is a DOM element.
			 *
			 * |Name  |Desc                          |
			 * |------|------------------------------|
			 * |val   |Value to check                |
			 * |return|True if value is a DOM element|
			 */
			/* example
			 * isEl(document.body); // -> true
			 */
			exports = function(val) {
					return !!(val && val.nodeType === 1);
			};
			return exports;
	})({});
	_.isEmail = (function (exports) {
			/* Loosely validate an email address.
			 *
			 * |Name  |Desc                                 |
			 * |------|-------------------------------------|
			 * |val   |Value to check                       |
			 * |return|True if value is an email like string|
			 */
			/* example
			 * isEmail('surunzi@foxmail.com'); // -> true
			 */
			exports = function(val) {
					return regEmail.test(val);
			};
			var regEmail = /.+@.+\..+/;
			return exports;
	})({});
	var isStr = _.isStr = (function (exports) {
			/* Check if value is a string primitive.
			 *
			 * |Name  |Desc                               |
			 * |------|-----------------------------------|
			 * |val   |Value to check                     |
			 * |return|True if value is a string primitive|
			 */
			/* example
			 * isStr('licia'); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object String]';
			};
			return exports;
	})({});
	_.isEmpty = (function (exports) {
			/* Check if value is an empty object or array.
			 *
			 * |Name  |Desc                  |
			 * |------|----------------------|
			 * |val   |Value to check        |
			 * |return|True if value is empty|
			 */
			/* example
			 * isEmpty([]); // -> true
			 * isEmpty({}); // -> true
			 * isEmpty(''); // -> true
			 */
			exports = function(val) {
					if (val == null) return true;
					if (isArrLike(val) && (isArr(val) || isStr(val) || isArgs(val))) {
							return val.length === 0;
					}
					return keys(val).length === 0;
			};
			return exports;
	})({});
	_.isEqual = (function (exports) {
			/* Performs an optimized deep comparison between the two objects, to determine if they should be considered equal.
			 *
			 * |Name  |Desc                         |
			 * |------|-----------------------------|
			 * |val   |Value to compare             |
			 * |other |Other value to compare       |
			 * |return|True if values are equivalent|
			 */
			/* example
			 * isEqual([1, 2, 3], [1, 2, 3]); // -> true
			 */
			exports = function(a, b) {
					return eq(a, b);
			};
			function deepEq(a, b, aStack, bStack) {
					var className = toString.call(a);
					if (className !== toString.call(b)) return false;
					switch (className) {
							case '[object RegExp]':
							case '[object String]':
									return '' + a === '' + b;
							case '[object Number]':
									if (+a !== +a) return +b !== +b;
									return +a === 0 ? 1 / +a === 1 / b : +a === +b;
							case '[object Date]':
							case '[object Boolean]':
									return +a === +b;
					}
					var areArrays = className === '[object Array]';
					if (!areArrays) {
							if (typeof a != 'object' || typeof b != 'object') return false;
							var aCtor = a.constructor;
							var bCtor = b.constructor;
							if (
									aCtor !== bCtor &&
									!(
											isFn(aCtor) &&
											aCtor instanceof aCtor &&
											isFn(bCtor) &&
											bCtor instanceof bCtor
									) &&
									'constructor' in a &&
									'constructor' in b
							)
									return false;
					}
					aStack = aStack || [];
					bStack = bStack || [];
					var length = aStack.length;
					while (length--) {
							if (aStack[length] === a) return bStack[length] === b;
					}
					aStack.push(a);
					bStack.push(b);
					if (areArrays) {
							length = a.length;
							if (length !== b.length) return false;
							while (length--) {
									if (!eq(a[length], b[length], aStack, bStack)) return false;
							}
					} else {
							var _keys = keys(a);
							var key;
							length = _keys.length;
							if (keys(b).length !== length) return false;
							while (length--) {
									key = _keys[length];
									if (!(has(b, key) && eq(a[key], b[key], aStack, bStack)))
											return false;
							}
					}
					aStack.pop();
					bStack.pop();
					return true;
			}
			function eq(a, b, aStack, bStack) {
					if (a === b) return a !== 0 || 1 / a === 1 / b;
					if (a == null || b == null) return a === b;
					if (a !== a) return b !== b;
					var type = typeof a;
					if (type !== 'function' && type !== 'object' && typeof b != 'object')
							return false;
					return deepEq(a, b, aStack, bStack);
			}
			return exports;
	})({});
	_.isErr = (function (exports) {
			/* Check if value is an error.
			 *
			 * |Name  |Desc                     |
			 * |------|-------------------------|
			 * |val   |Value to check           |
			 * |return|True if value is an error|
			 */
			/* example
			 * isErr(new Error()); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object Error]';
			};
			return exports;
	})({});
	var isInt = _.isInt = (function (exports) {
			/* Checks if value is classified as a Integer.
			 *
			 * |Name  |Desc                                 |
			 * |------|-------------------------------------|
			 * |val   |Value to check                       |
			 * |return|True if value is correctly classified|
			 */
			/* example
			 * isInt(5); // -> true
			 * isInt(5.1); // -> false
			 * isInt({}); // -> false
			 */
			exports = function(val) {
					return isNum(val) && val % 1 === 0;
			};
			return exports;
	})({});
	_.isEven = (function (exports) {
			/* Check if number is even.
			 *
			 * |Name  |Desc                  |
			 * |------|----------------------|
			 * |num   |Number to check       |
			 * |return|True if number is even|
			 */
			/* example
			 * isEven(0); // -> true
			 * isEven(1); // -> false
			 * isEven(2); // -> true
			 */
			exports = function(num) {
					if (!isInt(num)) return false;
					return num % 2 === 0;
			};
			return exports;
	})({});
	_.isFile = (function (exports) {
			/* Check if value is a file.
			 *
			 * |Name  |Desc                   |
			 * |------|-----------------------|
			 * |val   |Value to check         |
			 * |return|True if value is a file|
			 */
			/* example
			 * isFile(new File(['test'], 'test.txt', { type: 'text/plain' })); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object File]';
			};
			return exports;
	})({});
	var isFinite = _.isFinite = (function (exports) {
			/* Check if value is a finite primitive number.
			 *
			 * |Name  |Desc                            |
			 * |------|--------------------------------|
			 * |val   |Value to check                  |
			 * |return|True if value is a finite number|
			 */
			/* example
			 * isFinite(3); // -> true
			 * isFinite(Infinity); // -> false
			 */
			var nativeIsFinite = root.isFinite;
			var nativeIsNaN = root.isNaN;
			exports = function(val) {
					return nativeIsFinite(val) && !nativeIsNaN(parseFloat(val));
			};
			return exports;
	})({});
	_.isFullWidth = (function (exports) {
			/* Check if character is full width.
			 *
			 * |Name     |Desc                           |
			 * |---------|-------------------------------|
			 * |codePoint|Unicode code point             |
			 * |return   |True if character is full width|
			 */
			/* example
			 * isFullWidth('a'.codePointAt(0)); // -> false
			 * isFullWidth(','.codePointAt(0)); // -> false
			 * isFullWidth('我'.codePointAt(0)); // -> true
			 * isFullWidth('，'.codePointAt(0)); // -> true
			 */
			exports = function isFullWidth(c) {
					if (!isInt(c)) {
							return false;
					}
					/* https://unicode.org/Public/UNIDATA/EastAsianWidth.txt
					 * Characters with East_Asian_Width property W or F.
					 */
					return (
							c >= 0x1100 &&
							(c <= 0x115f ||
									c === 0x2329 ||
									c === 0x232a ||
									(0x2e80 <= c && c <= 0x3247 && c !== 0x303f) ||
									(0x3250 <= c && c <= 0x4dbf) ||
									(0x4e00 <= c && c <= 0xa4c6) ||
									(0xa960 <= c && c <= 0xa97c) ||
									(0xac00 <= c && c <= 0xd7a3) ||
									(0xf900 <= c && c <= 0xfaff) ||
									(0xfe10 <= c && c <= 0xfe19) ||
									(0xfe30 <= c && c <= 0xfe6b) ||
									(0xff01 <= c && c <= 0xff60) ||
									(0xffe0 <= c && c <= 0xffe6) ||
									(0x1b000 <= c && c <= 0x1b001) ||
									(0x1f200 <= c && c <= 0x1f251) ||
									(0x20000 <= c && c <= 0x3fffd))
					);
			};
			return exports;
	})({});
	_.isGeneratorFn = (function (exports) {
			/* Check if value is a generator function.
			 *
			 * |Name  |Desc                                 |
			 * |------|-------------------------------------|
			 * |val   |Value to check                       |
			 * |return|True if value is a generator function|
			 */
			/* example
			 * isGeneratorFn(function*() {}); // -> true
			 * isGeneratorFn(function() {}); // -> false
			 */
			exports = function(val) {
					return objToStr(val) === '[object GeneratorFunction]';
			};
			return exports;
	})({});
	_.isHidden = (function (exports) {
			/* Check if element is hidden.
			 *
			 * |Name   |Desc                     |
			 * |-------|-------------------------|
			 * |el     |Target element           |
			 * |options|Check options            |
			 * |return |True if element is hidden|
			 *
			 * Available options:
			 *
			 * |Name            |Desc                         |
			 * |----------------|-----------------------------|
			 * |display=true    |Check if it is displayed     |
			 * |visibility=false|Check visibility css property|
			 * |opacity=false   |Check opacity css property   |
			 * |size=false      |Check width and height       |
			 * |viewport=false  |Check if it is in viewport   |
			 * |overflow=false  |Check if hidden in overflow  |
			 */

			/* example
			 * isHidden(document.createElement('div')); // -> true
			 */
			var getComputedStyle = root.getComputedStyle;
			var document = root.document;
			exports = function(el) {
					var _ref =
									arguments.length > 1 && arguments[1] !== undefined
											? arguments[1]
											: {},
							_ref$display = _ref.display,
							display = _ref$display === void 0 ? true : _ref$display,
							_ref$visibility = _ref.visibility,
							visibility = _ref$visibility === void 0 ? false : _ref$visibility,
							_ref$opacity = _ref.opacity,
							opacity = _ref$opacity === void 0 ? false : _ref$opacity,
							_ref$size = _ref.size,
							size = _ref$size === void 0 ? false : _ref$size,
							_ref$viewport = _ref.viewport,
							viewport = _ref$viewport === void 0 ? false : _ref$viewport,
							_ref$overflow = _ref.overflow,
							overflow = _ref$overflow === void 0 ? false : _ref$overflow;
					if (display) {
							return el.offsetParent === null;
					}
					var computedStyle = getComputedStyle(el);
					if (visibility && computedStyle.visibility === 'hidden') {
							return true;
					}
					if (opacity) {
							if (computedStyle.opacity === '0') {
									return true;
							} else {
									var cur = el;
									while ((cur = cur.parentElement)) {
											var _computedStyle = getComputedStyle(cur);

											if (_computedStyle.opacity === '0') {
													return true;
											}
									}
							}
					}
					var clientRect = el.getBoundingClientRect();
					if (size && (clientRect.width === 0 || clientRect.height === 0)) {
							return true;
					}
					if (viewport) {
							var containerRect = {
									top: 0,
									left: 0,
									right: document.documentElement.clientWidth,
									bottom: document.documentElement.clientHeight
							};
							return isOutside(clientRect, containerRect);
					}
					if (overflow) {
							var _cur = el;
							while ((_cur = _cur.parentElement)) {
									var _computedStyle2 = getComputedStyle(_cur);

									var _overflow = _computedStyle2.overflow;

									if (_overflow === 'scroll' || _overflow === 'hidden') {
											var curRect = _cur.getBoundingClientRect();

											if (isOutside(clientRect, curRect)) return true;
									}
							}
					}
					return false;
			};
			function isOutside(clientRect, containerRect) {
					return (
							clientRect.right < containerRect.left ||
							clientRect.left > containerRect.right ||
							clientRect.bottom < containerRect.top ||
							clientRect.top > containerRect.bottom
					);
			}
			return exports;
	})({});
	_.isIp = (function (exports) {
			/* Check if value is an IP address.
			 *
			 * |Name  |Desc                          |
			 * |------|------------------------------|
			 * |str   |String to check               |
			 * |return|True if value is an IP address|
			 *
			 * ### v4
			 *
			 * Check if value is an IPv4 address.
			 *
			 * ### v6
			 *
			 * Check if value is an IPv6 address.
			 */
			/* example
			 * isIp('192.168.191.1'); // -> true
			 * isIp('1:2:3:4:5:6:7:8'); // -> true
			 * isIp('test'); // -> false
			 * isIp.v4('192.168.191.1'); // -> true
			 * isIp.v6('1:2:3:4:5:6:7:8'); // -> true
			 */
			exports = function(str) {
					return exports.v4(str) || exports.v6(str);
			}; // https://github.com/sindresorhus/ip-regex
			var v4 =
					'(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)(?:\\.(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)){3}';
			var regV4 = new RegExp('^'.concat(v4, '$'));
			var v6seg = '[a-fA-F\\d]{1,4}';
			var v6 = [
					'(',
					'(?:'.concat(v6seg, ':){7}(?:').concat(v6seg, '|:)|'),
					'(?:'
							.concat(v6seg, ':){6}(?:')
							.concat(v4, '|:')
							.concat(v6seg, '|:)|'),
					'(?:'
							.concat(v6seg, ':){5}(?::')
							.concat(v4, '|(:')
							.concat(v6seg, '){1,2}|:)|'),
					'(?:'
							.concat(v6seg, ':){4}(?:(:')
							.concat(v6seg, '){0,1}:')
							.concat(v4, '|(:')
							.concat(v6seg, '){1,3}|:)|'),
					'(?:'
							.concat(v6seg, ':){3}(?:(:')
							.concat(v6seg, '){0,2}:')
							.concat(v4, '|(:')
							.concat(v6seg, '){1,4}|:)|'),
					'(?:'
							.concat(v6seg, ':){2}(?:(:')
							.concat(v6seg, '){0,3}:')
							.concat(v4, '|(:')
							.concat(v6seg, '){1,5}|:)|'),
					'(?:'
							.concat(v6seg, ':){1}(?:(:')
							.concat(v6seg, '){0,4}:')
							.concat(v4, '|(:')
							.concat(v6seg, '){1,6}|:)|'),
					'(?::((?::'
							.concat(v6seg, '){0,5}:')
							.concat(v4, '|(?::')
							.concat(v6seg, '){1,7}|:))'),
					')(%[0-9a-zA-Z]{1,})?'
			].join('');
			var regV6 = new RegExp('^'.concat(v6, '$'));
			exports.v4 = function(str) {
					return regV4.test(str);
			};
			exports.v6 = function(str) {
					return regV6.test(str);
			};
			return exports;
	})({});
	_.isJson = (function (exports) {
			/* Check if value is a valid JSON.
			 *
			 * It uses `JSON.parse()` and a `try... catch` block.
			 *
			 * |Name  |Desc                         |
			 * |------|-----------------------------|
			 * |val   |JSON string                  |
			 * |return|True if value is a valid JSON|
			 */
			/* example
			 * isJson('{"a": 5}'); // -> true
			 * isJson("{'a': 5}"); // -> false
			 */
			exports = function(val) {
					try {
							JSON.parse(val);
							return true;
					} catch (e) {
							return false;
					}
			};
			return exports;
	})({});
	_.isLeapYear = (function (exports) {
			/* Check if a year is a leap year.
			 *
			 * |Name  |Desc                       |
			 * |------|---------------------------|
			 * |year  |Year to check              |
			 * |return|True if year is a leap year|
			 */
			/* example
			 * isLeapYear(2000); // -> true
			 * isLeapYear(2002); // -> false
			 */
			exports = function(year) {
					return year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);
			};
			return exports;
	})({});
	_.isMap = (function (exports) {
			/* Check if value is a Map object.
			 *
			 * |Name  |Desc                  |
			 * |------|----------------------|
			 * |val   |Value to check        |
			 * |return|True if value is a Map|
			 */
			/* example
			 * isMap(new Map()); // -> true
			 * isMap(new WeakMap()); // -> false
			 */
			exports = function(val) {
					return objToStr(val) === '[object Map]';
			};

			return exports;
	})({});
	var isMatch = _.isMatch = (function (exports) {
			/* Check if keys and values in src are contained in obj.
			 *
			 * |Name  |Desc                              |
			 * |------|----------------------------------|
			 * |obj   |Object to inspect                 |
			 * |src   |Object of property values to match|
			 * |return|True if object is match           |
			 */
			/* example
			 * isMatch({ a: 1, b: 2 }, { a: 1 }); // -> true
			 */
			exports = function(obj, src) {
					var _keys = keys(src);
					var len = _keys.length;
					if (obj == null) return !len;
					obj = Object(obj);
					for (var i = 0; i < len; i++) {
							var key = _keys[i];
							if (src[key] !== obj[key] || !(key in obj)) return false;
					}
					return true;
			};
			return exports;
	})({});
	var memoize = _.memoize = (function (exports) {
			/* Memoize a given function by caching the computed result.
			 *
			 * |Name  |Desc                                |
			 * |------|------------------------------------|
			 * |fn    |Function to have its output memoized|
			 * |hashFn|Function to create cache key        |
			 * |return|New memoized function               |
			 */

			/* example
			 * const fibonacci = memoize(function(n) {
			 *     return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
			 * });
			 */
			exports = function(fn, hashFn) {
					var memoize = function(key) {
							var cache = memoize.cache;
							var address = '' + (hashFn ? hashFn.apply(this, arguments) : key);
							if (!has(cache, address)) cache[address] = fn.apply(this, arguments);
							return cache[address];
					};

					memoize.cache = {};
					return memoize;
			};

			return exports;
	})({});
	_.isMobile = (function (exports) {
			/* Check whether client is using a mobile browser using ua.
			 *
			 * |Name                  |Desc                                 |
			 * |----------------------|-------------------------------------|
			 * |ua=navigator.userAgent|User agent                           |
			 * |return                |True if ua belongs to mobile browsers|
			 */

			/* example
			 * isMobile(navigator.userAgent);
			 */
			var regMobileAll = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i;
			var regMobileFour = /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i;
			exports = memoize(function(ua) {
					ua = ua || (isBrowser ? navigator.userAgent : '');
					return regMobileAll.test(ua) || regMobileFour.test(ua.substr(0, 4));
			});

			return exports;
	})({});
	var isNaN = _.isNaN = (function (exports) {
			/* Check if value is an NaN.
			 *
			 * |Name  |Desc                   |
			 * |------|-----------------------|
			 * |val   |Value to check         |
			 * |return|True if value is an NaN|
			 *
			 * Undefined is not an NaN, different from global isNaN function.
			 */
			/* example
			 * isNaN(0); // -> false
			 * isNaN(NaN); // -> true
			 */
			exports = function(val) {
					return isNum(val) && val !== +val;
			};
			return exports;
	})({});
	var isNil = _.isNil = (function (exports) {
			/* Check if value is null or undefined, the same as value == null.
			 *
			 * |Name  |Desc                              |
			 * |------|----------------------------------|
			 * |val   |Value to check                    |
			 * |return|True if value is null or undefined|
			 */

			/* example
			 * isNil(null); // -> true
			 * isNil(void 0); // -> true
			 * isNil(undefined); // -> true
			 * isNil(false); // -> false
			 * isNil(0); // -> false
			 * isNil([]); // -> false
			 */
			exports = function(val) {
					return val == null;
			};
			return exports;
	})({});
	var toSrc = _.toSrc = (function (exports) {
			/* Convert function to its source code.
			 *
			 * |Name  |Desc               |
			 * |------|-------------------|
			 * |fn    |Function to convert|
			 * |return|Source code        |
			 */
			/* example
			 * toSrc(Math.min); // -> 'function min() { [native code] }'
			 * toSrc(function() {}); // -> 'function () { }'
			 */
			exports = function(fn) {
					if (isNil(fn)) return '';
					try {
							return fnToStr.call(fn);
							/* eslint-disable no-empty */
					} catch (e) {}
					try {
							return fn + '';
							/* eslint-disable no-empty */
					} catch (e) {}
					return '';
			};
			var fnToStr = Function.prototype.toString;
			return exports;
	})({});
	_.isNative = (function (exports) {
			/* Check if value is a native function.
			 *
			 * |Name  |Desc                              |
			 * |------|----------------------------------|
			 * |val   |Value to check                    |
			 * |return|True if value is a native function|
			 */
			/* example
			 * isNative(function() {}); // -> false
			 * isNative(Math.min); // -> true
			 */
			exports = function(val) {
					if (!isObj(val)) return false;
					if (isFn(val)) return regIsNative.test(toSrc(val)); // Detect host constructors (Safari > 4; really typed array specific)

					return regIsHostCtor.test(toSrc(val));
			};
			var hasOwnProperty = Object.prototype.hasOwnProperty;
			var regIsNative = new RegExp(
					'^' +
							toSrc(hasOwnProperty)
									.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
									.replace(
											/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,
											'$1.*?'
									) +
							'$'
			);
			var regIsHostCtor = /^\[object .+?Constructor\]$/;
			return exports;
	})({});
	_.isNode = (function (exports) {
			/* Check if running in node.
			 */
			/* example
			 * console.log(isNode); // -> true if running in node
			 */
			exports =
					typeof process !== 'undefined' && objToStr(process) === '[object process]';

			return exports;
	})({});
	_.isNull = (function (exports) {
			/* Check if value is an Null.
			 *
			 * |Name  |Desc                    |
			 * |------|------------------------|
			 * |val   |Value to check          |
			 * |return|True if value is an Null|
			 */

			/* example
			 * isNull(null); // -> true
			 */
			exports = function(val) {
					return val === null;
			};
			return exports;
	})({});
	_.isNumeric = (function (exports) {
			/* Check if value is numeric.
			 *
			 * |Name  |Desc                    |
			 * |------|------------------------|
			 * |val   |Value to check          |
			 * |return|True if value is numeric|
			 */
			/* example
			 * isNumeric(1); // -> true
			 * isNumeric('1'); // -> true
			 * isNumeric(Number.MAX_VALUE); // -> true
			 * isNumeric(0xff); // -> true
			 * isNumeric(''); // -> false
			 * isNumeric('1.1.1'); // -> false
			 * isNumeric(NaN); // -> false
			 */
			exports = function(val) {
					if (isStr(val)) val = val.replace(regComma, '');
					return !isNaN(parseFloat(val)) && isFinite(val) && !isArr(val);
			};
			var regComma = /,/g;
			return exports;
	})({});
	_.isOdd = (function (exports) {
			/* Check if number is odd.
			 *
			 * |Name  |Desc                 |
			 * |------|---------------------|
			 * |num   |Number to check      |
			 * |return|True if number is odd|
			 */
			/* example
			 * isOdd(0); // -> false
			 * isOdd(1); // -> true
			 * isOdd(2); // -> false
			 */
			exports = function(num) {
					if (!isInt(num)) return false;
					return num % 2 !== 0;
			};
			return exports;
	})({});
	_.isPlainObj = (function (exports) {
			/* Check if value is an object created by Object constructor.
			 *
			 * |Name  |Desc                           |
			 * |------|-------------------------------|
			 * |val   |Value to check                 |
			 * |return|True if value is a plain object|
			 */
			/* example
			 * isPlainObj({}); // -> true
			 * isPlainObj([]); // -> false
			 * isPlainObj(function() {}); // -> false
			 */
			exports = function(val) {
					if (!isObj(val)) return false;
					var ctor = val.constructor;
					if (!isFn(ctor)) return false;
					if (!has(ctor.prototype, 'isPrototypeOf')) return false;
					return !isArr(val) && !isFn(val);
			};
			return exports;
	})({});

	_.isPrime = (function (exports) {
			/* Check if the provided integer is a prime number.
			 *
			 * |Name  |Desc                            |
			 * |------|--------------------------------|
			 * |num   |Number to check                 |
			 * |return|True if number is a prime number|
			 */
			/* example
			 * isPrime(11); // -> true
			 * isPrime(8); // -> false
			 */
			exports = function(num) {
					var boundary = Math.floor(Math.sqrt(num));

					for (var i = 2; i <= boundary; i++) {
							if (num % i === 0) {
									return false;
							}
					}
					return num >= 2;
			};
			return exports;
	})({});
	_.isPrimitive = (function (exports) {
			/* Check if value is string, number, boolean or null.
			 *
			 * |Name  |Desc                        |
			 * |------|----------------------------|
			 * |val   |Value to check              |
			 * |return|True if value is a primitive|
			 */
			/* example
			 * isPrimitive(5); // -> true
			 * isPrimitive('abc'); // -> true
			 * isPrimitive(false); // -> true
			 */
			exports = function(val) {
					var type = typeof val;
					return val == null || (type !== 'function' && type !== 'object');
			};

			return exports;
	})({});
	_.isPromise = (function (exports) {
			/* Check if value looks like a promise.
			 *
			 * |Name  |Desc                              |
			 * |------|----------------------------------|
			 * |val   |Value to check                    |
			 * |return|True if value looks like a promise|
			 */
			/* example
			 * isPromise(new Promise(function() {})); // -> true
			 * isPromise({}); // -> false
			 */
			exports = function(val) {
					return isObj(val) && isFn(val.then) && isFn(val.catch);
			};
			return exports;
	})({});
	_.isRegExp = (function (exports) {
			/* Check if value is a regular expression.
			 *
			 * |Name  |Desc                                 |
			 * |------|-------------------------------------|
			 * |val   |Value to check                       |
			 * |return|True if value is a regular expression|
			 */
			/* example
			 * isRegExp(/a/); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object RegExp]';
			};
			return exports;
	})({});
	_.isRelative = (function (exports) {
			/* Check if path appears to be relative.
			 *
			 * |Name  |Desc                               |
			 * |------|-----------------------------------|
			 * |path  |Path to check                      |
			 * |return|True if path appears to be relative|
			 */
			exports = function(path) {
					return !regAbsolute.test(path);
			};
			var regAbsolute = /^([a-z]+:)?[\\/]/i;
			return exports;
	})({});
	_.isRetina = (function (exports) {
			/* Determine if running on a high DPR device or not.
			 */

			/* example
			 * console.log(isRetina); // -> true if high DPR
			 */
			var mediaQuery =
					'(-webkit-min-device-pixel-ratio: 1.25), (min--moz-device-pixel-ratio: 1.25), (-o-min-device-pixel-ratio: 5/4), (min-resolution: 1.25dppx)';
			exports =
					isBrowser &&
					(window.devicePixelRatio > 1.25 ||
							(window.matchMedia && window.matchMedia(mediaQuery).matches));
			return exports;
	})({});
	_.isRunning = (function (exports) {
			/* Check if process is running.
			 *
			 * |Name  |Desc                      |
			 * |------|--------------------------|
			 * |pid   |Process id                |
			 * |return|True if process is running|
			 */
			exports = function(pid) {
					try {
							return process.kill(pid, 0);
					} catch (e) {
							return e.code === 'EPERM';
					}
			};
			return exports;
	})({});
	_.isSet = (function (exports) {
			/* Check if value is a Set object.
			 *
			 * |Name  |Desc                  |
			 * |------|----------------------|
			 * |val   |Value to check        |
			 * |return|True if value is a Set|
			 */

			/* example
			 * isSet(new Set()); // -> true
			 * isSet(new WeakSet()); // -> false
			 */
			exports = function(val) {
					return objToStr(val) === '[object Set]';
			};
			return exports;
	})({});

	/* ------------------------------ isSorted ------------------------------ */
	_.isSorted = (function (exports) {
			/* Check if an array is sorted.
			 *
			 * |Name  |Desc                   |
			 * |------|-----------------------|
			 * |arr   |Array to check         |
			 * |cmp   |Comparator             |
			 * |return|True if array is sorted|
			 */

			/* example
			 * isSorted([1, 2, 3]); // -> true
			 * isSorted([3, 2, 1]); // -> false
			 */
			exports = function(arr) {
					var cmp =
							arguments.length > 1 && arguments[1] !== undefined
									? arguments[1]
									: exports.defComparator;

					for (var i = 0, len = arr.length; i < len - 1; i++) {
							if (cmp(arr[i], arr[i + 1]) > 0) return false;
					}
					return true;
			};
			exports.defComparator = function(a, b) {
					if (a < b) return -1;
					if (a > b) return 1;
					return 0;
			};
			return exports;
	})({});
	_.isStream = (function (exports) {
			/* Check if value is a Node.js stream.
			 *
			 * |Name  |Desc                             |
			 * |------|---------------------------------|
			 * |val   |Value to check                   |
			 * |return|True if value is a Node.js stream|
			 */

			/* example
			 * const stream = require('stream');
			 *
			 * isStream(new stream.Stream()); // -> true
			 */
			exports = function(val) {
					return val !== null && isObj(val) && isFn(val.pipe);
			};
			return exports;
	})({});
	_.isSymbol = (function (exports) {
			/* Check if value is a symbol.
			 *
			 * |Name  |Desc                     |
			 * |------|-------------------------|
			 * |val   |Value to check           |
			 * |return|True if value is a symbol|
			 */
			/* example
			 * isSymbol(Symbol('test')); // -> true
			 */
			exports = function(val) {
					return typeof val === 'symbol';
			};
			return exports;
	})({});
	_.isTypedArr = (function (exports) {
			/* Check if value is a typed array.
			 *
			 * |Name  |Desc                          |
			 * |------|------------------------------|
			 * |val   |Value to check                |
			 * |return|True if value is a typed array|
			 */
			/* example
			 * isTypedArr([]); // -> false
			 * isTypedArr(new Uint8Array(8)); // -> true
			 */
			exports = function(val) {
					return !!map[objToStr(val)];
			};
			var map = {};
			each(
					[
							'Int8Array',
							'Int16Array',
							'Int32Array',
							'Uint8Array',
							'Uint8ClampedArray',
							'Uint16Array',
							'Uint32Array',
							'Float32Array',
							'Float64Array'
					],
					function(val) {
							map['[object ' + val + ']'] = true;
					}
			);
			return exports;
	})({});
	_.isUrl = (function (exports) {
			/* Loosely validate an url.
			 *
			 * |Name  |Desc                               |
			 * |------|-----------------------------------|
			 * |val   |Value to check                     |
			 * |return|True if value is an url like string|
			 */
			/* example
			 * isUrl('http://www.example.com?foo=bar&param=test'); // -> true
			 */
			exports = function(val) {
					return regUrl.test(val);
			};
			var regUrl = /^(?:\w+:)?\/\/([^\s.]+\.\S{2}|localhost[:?\d]*)\S*$/;
			return exports;
	})({});
	_.isWeakMap = (function (exports) {
			/* Check if value is a WeakMap object.
			 *
			 * |Name  |Desc                      |
			 * |------|--------------------------|
			 * |val   |Value to check            |
			 * |return|True if value is a WeakMap|
			 */

			/* example
			 * isWeakMap(new Map()); // -> false
			 * isWeakMap(new WeakMap()); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object WeakMap]';
			};
			return exports;
	})({});
	_.isWeakSet = (function (exports) {
			/* Check if value is a WeakSet object.
			 *
			 * |Name  |Desc                      |
			 * |------|--------------------------|
			 * |val   |Value to check            |
			 * |return|True if value is a WeakSet|
			 */

			/* example
			 * isWeakSet(new Set()); // -> false
			 * isWeakSet(new WeakSet()); // -> true
			 */
			exports = function(val) {
					return objToStr(val) === '[object WeakSet]';
			};
			return exports;
	})({});
	_.isWindows = (function (exports) {
			/* Check if platform is windows.
			 */

			/* example
			 * console.log(isWindows); // -> true if running on windows
			 */
			exports = false;
			if (typeof process !== 'undefined') {
					exports =
							process.platform === 'win32' ||
							process.env.OSTYPE === 'cygwin' ||
							process.env.OSTYPE === 'msys';
			}
			return exports;
	})({});
	var ltrim = _.ltrim = (function (exports) {
			/* Remove chars or white-spaces from beginning of string.
			 *
			 * |Name  |Desc              |
			 * |------|------------------|
			 * |str   |String to trim    |
			 * |chars |Characters to trim|
			 * |return|Trimmed string    |
			 */

			/* example
			 * ltrim(' abc  '); // -> 'abc  '
			 * ltrim('_abc_', '_'); // -> 'abc_'
			 * ltrim('_abc_', ['a', '_']); // -> 'bc_'
			 */
			var regSpace = /^\s+/;

			exports = function(str, chars) {
					if (chars == null) return str.replace(regSpace, '');
					var start = 0;
					var len = str.length;
					var charLen = chars.length;
					var found = true;
					var i;
					var c;
					while (found && start < len) {
							found = false;
							i = -1;
							c = str.charAt(start);

							while (++i < charLen) {
									if (c === chars[i]) {
											found = true;
											start++;
											break;
									}
							}
					}
					return start >= len ? '' : str.substr(start, len);
			};
			return exports;
	})({});
	var matcher = _.matcher = (function (exports) {
			/* Return a predicate function that checks if attrs are contained in an object.
			 *
			 * |Name  |Desc                              |
			 * |------|----------------------------------|
			 * |attrs |Object of property values to match|
			 * |return|New predicate function            |
			 */

			/* example
			 * const filter = require('licia/filter');
			 *
			 * const objects = [
			 *     { a: 1, b: 2, c: 3 },
			 *     { a: 4, b: 5, c: 6 }
			 * ];
			 * filter(objects, matcher({ a: 4, c: 6 })); // -> [{a: 4, b: 5, c: 6}]
			 */
			exports = function(attrs) {
					attrs = extendOwn({}, attrs);
					return function(obj) {
							return isMatch(obj, attrs);
					};
			};
			return exports;
	})({});
	var restArgs = _.restArgs = (function (exports) {
			/* This accumulates the arguments passed into an array, after a given index.
			 *
			 * |Name      |Desc                                   |
			 * |----------|---------------------------------------|
			 * |function  |Function that needs rest parameters    |
			 * |startIndex|The start index to accumulates         |
			 * |return    |Generated function with rest parameters|
			 */

			/* example
			 * const paramArr = restArgs(function(rest) {
			 *     return rest;
			 * });
			 * paramArr(1, 2, 3, 4); // -> [1, 2, 3, 4]
			 */
			exports = function(fn, startIdx) {
					startIdx = startIdx == null ? fn.length - 1 : +startIdx;
					return function() {
							var len = Math.max(arguments.length - startIdx, 0);
							var rest = new Array(len);
							var i;
							for (i = 0; i < len; i++) {
									rest[i] = arguments[i + startIdx];
							} // Call runs faster than apply.
							switch (startIdx) {
									case 0:
											return fn.call(this, rest);
									case 1:
											return fn.call(this, arguments[0], rest);
									case 2:
											return fn.call(this, arguments[0], arguments[1], rest);
							}
							var args = new Array(startIdx + 1);
							for (i = 0; i < startIdx; i++) {
									args[i] = arguments[i];
							}
							args[startIdx] = rest;
							return fn.apply(this, args);
					};
			};
			return exports;
	})({});

	/* ------------------------------ property ------------------------------ */

	var property = _.property = (function (exports) {
			/* Return a function that will itself return the key property of any passed-in object.
			 *
			 * |Name  |Desc                       |
			 * |------|---------------------------|
			 * |path  |Path of the property to get|
			 * |return|New accessor function      |
			 */

			/* example
			 * const obj = { a: { b: 1 } };
			 * property('a')(obj); // -> {b: 1}
			 * property(['a', 'b'])(obj); // -> 1
			 */
			exports = function(path) {
					if (!isArr(path)) return shallowProperty(path);
					return function(obj) {
							return safeGet(obj, path);
					};
			};
			function shallowProperty(key) {
					return function(obj) {
							return obj == null ? void 0 : obj[key];
					};
			}
			return exports;
	})({});

	/* ------------------------------ safeCb ------------------------------ */

	var safeCb = _.safeCb = (function (exports) {
			/* Create callback based on input value.
			 */
			exports = function(val, ctx, argCount) {
					if (val == null) return identity;
					if (isFn(val)) return optimizeCb(val, ctx, argCount);
					if (isObj(val) && !isArr(val)) return matcher(val);
					return property(val);
			};
			return exports;
	})({});
	var filter = _.filter = (function (exports) {
			/* Iterates over elements of collection, returning an array of all the values that pass a truth test.
			 *
			 * |Name     |Desc                                   |
			 * |---------|---------------------------------------|
			 * |obj      |Collection to iterate over             |
			 * |predicate|Function invoked per iteration         |
			 * |ctx      |Predicate context                      |
			 * |return   |Array of all values that pass predicate|
			 */

			/* example
			 * filter([1, 2, 3, 4, 5], function(val) {
			 *     return val % 2 === 0;
			 * }); // -> [2, 4]
			 */
			exports = function(obj, predicate, ctx) {
					var ret = [];
					predicate = safeCb(predicate, ctx);
					each(obj, function(val, idx, list) {
							if (predicate(val, idx, list)) ret.push(val);
					});
					return ret;
			};
			return exports;
	})({});
	var unique = _.unique = (function (exports) {
			/* Create duplicate-free version of an array.
			 *
			 * |Name  |Desc                         |
			 * |------|-----------------------------|
			 * |arr   |Array to inspect             |
			 * |cmp   |Function for comparing values|
			 * |return|New duplicate free array     |
			 */

			/* example
			 * unique([1, 2, 3, 1]); // -> [1, 2, 3]
			 */
			exports = function(arr, cmp) {
					cmp = cmp || isEqual;
					return filter(arr, function(item, idx, arr) {
							var len = arr.length;

							while (++idx < len) {
									if (cmp(item, arr[idx])) return false;
							}

							return true;
					});
			};
			function isEqual(a, b) {
					return a === b;
			}
			return exports;
	})({});
	var allKeys = _.allKeys = (function (exports) {
			/* Retrieve all the names of object's own and inherited properties.
			 *
			 * |Name   |Desc                       |
			 * |-------|---------------------------|
			 * |obj    |Object to query            |
			 * |options|Options                    |
			 * |return |Array of all property names|
			 *
			 * Available options:
			 *
			 * |Name              |Desc                     |
			 * |------------------|-------------------------|
			 * |prototype=true    |Include prototype keys   |
			 * |unenumerable=false|Include unenumerable keys|
			 * |symbol=false      |Include symbol keys      |
			 *
			 * Members of Object's prototype won't be retrieved.
			 */

			/* example
			 * const obj = Object.create({ zero: 0 });
			 * obj.one = 1;
			 * allKeys(obj); // -> ['zero', 'one']
			 */
			var getOwnPropertyNames = Object.getOwnPropertyNames;
			var getOwnPropertySymbols = Object.getOwnPropertySymbols;

			exports = function(obj) {
					var _ref =
									arguments.length > 1 && arguments[1] !== undefined
											? arguments[1]
											: {},
							_ref$prototype = _ref.prototype,
							prototype = _ref$prototype === void 0 ? true : _ref$prototype,
							_ref$unenumerable = _ref.unenumerable,
							unenumerable = _ref$unenumerable === void 0 ? false : _ref$unenumerable,
							_ref$symbol = _ref.symbol,
							symbol = _ref$symbol === void 0 ? false : _ref$symbol;

					var ret = [];

					if ((unenumerable || symbol) && getOwnPropertyNames) {
							var getKeys = keys;
							if (unenumerable && getOwnPropertyNames) getKeys = getOwnPropertyNames;

							do {
									ret = ret.concat(getKeys(obj));

									if (symbol && getOwnPropertySymbols) {
											ret = ret.concat(getOwnPropertySymbols(obj));
									}
							} while (
									prototype &&
									(obj = getProto(obj)) &&
									obj !== Object.prototype
							);

							ret = unique(ret);
					} else {
							if (prototype) {
									for (var key in obj) {
											ret.push(key);
									}
							} else {
									ret = keys(obj);
							}
					}
					return ret;
			};
			return exports;
	})({});
	var extend = _.extend = (function (exports) {
			/* Copy all of the properties in the source objects over to the destination object.
			 *
			 * |Name       |Desc              |
			 * |-----------|------------------|
			 * |destination|Destination object|
			 * |...sources |Sources objects   |
			 * |return     |Destination object|
			 */

			/* example
			 * extend({ name: 'RedHood' }, { age: 24 }); // -> {name: 'RedHood', age: 24}
			 */
			exports = createAssigner(allKeys);
			return exports;
	})({});
	var clone = _.clone = (function (exports) {
			/* Create a shallow-copied clone of the provided plain object.
			 *
			 * Any nested objects or arrays will be copied by reference, not duplicated.
			 *
			 * |Name  |Desc          |
			 * |------|--------------|
			 * |val   |Value to clone|
			 * |return|Cloned value  |
			 */
			/* example
			 * clone({ name: 'eustia' }); // -> {name: 'eustia'}
			 */
			exports = function(obj) {
					if (!isObj(obj)) return obj;
					return isArr(obj) ? obj.slice() : extend({}, obj);
			};
			return exports;
	})({});
	var map = _.map = (function (exports) {
			/* Create an array of values by running each element in collection through iteratee.
			 *
			 * |Name    |Desc                          |
			 * |--------|------------------------------|
			 * |object  |Collection to iterate over    |
			 * |iterator|Function invoked per iteration|
			 * |context |Function context              |
			 * |return  |New mapped array              |
			 */

			/* example
			 * map([4, 8], function(n) {
			 *     return n * n;
			 * }); // -> [16, 64]
			 */
			exports = function(obj, iterator, ctx) {
					iterator = safeCb(iterator, ctx);
					var _keys = !isArrLike(obj) && keys(obj);
					var len = (_keys || obj).length;
					var results = Array(len);
					for (var i = 0; i < len; i++) {
							var curKey = _keys ? _keys[i] : i;
							results[i] = iterator(obj[curKey], curKey, obj);
					}
					return results;
			};
			return exports;
	})({});
	var toArr = _.toArr = (function (exports) {
			/* Convert value to an array.
			 *
			 * |Name  |Desc            |
			 * |------|----------------|
			 * |val   |Value to convert|
			 * |return|Converted array |
			 */

			/* example
			 * toArr({ a: 1, b: 2 }); // -> [{a: 1, b: 2}]
			 * toArr('abc'); // -> ['abc']
			 * toArr(1); // -> [1]
			 * toArr(null); // -> []
			 */
			exports = function(val) {
					if (!val) return [];
					if (isArr(val)) return val;
					if (isArrLike(val) && !isStr(val)) return map(val);
					return [val];
			};
			return exports;
	})({});
	var Class = _.Class = (function (exports) {
			/* Create JavaScript class.
			 *
			 * |Name   |Desc                             |
			 * |-------|---------------------------------|
			 * |methods|Public methods                   |
			 * [statics|Static methods                   |
			 * |return |Function used to create instances|
			 */

			/* example
			 * const People = Class({
			 *     initialize: function People(name, age) {
			 *         this.name = name;
			 *         this.age = age;
			 *     },
			 *     introduce: function() {
			 *         return 'I am ' + this.name + ', ' + this.age + ' years old.';
			 *     }
			 * });
			 *
			 * const Student = People.extend(
			 *     {
			 *         initialize: function Student(name, age, school) {
			 *             this.callSuper(People, 'initialize', arguments);
			 *
			 *             this.school = school;
			 *         },
			 *         introduce: function() {
			 *             return (
			 *                 this.callSuper(People, 'introduce') +
			 *                 '\n I study at ' +
			 *                 this.school +
			 *                 '.'
			 *             );
			 *         }
			 *     },
			 *     {
			 *         is: function(obj) {
			 *             return obj instanceof Student;
			 *         }
			 *     }
			 * );
			 *
			 * const a = new Student('allen', 17, 'Hogwarts');
			 * a.introduce(); // -> 'I am allen, 17 years old. \n I study at Hogwarts.'
			 * Student.is(a); // -> true
			 */
			exports = function(methods, statics) {
					return Base.extend(methods, statics);
			};

			function makeClass(parent, methods, statics) {
					statics = statics || {};
					var className =
							methods.className || safeGet(methods, 'initialize.name') || '';
					delete methods.className;

					var ctor = function() {
							var args = toArr(arguments);
							return this.initialize
									? this.initialize.apply(this, args) || this
									: this;
					};

					if (!isMiniProgram) {
							// unsafe-eval CSP violation
							try {
									ctor = new Function(
											'toArr',
											'return function ' +
													className +
													'()' +
													'{' +
													'var args = toArr(arguments);' +
													'return this.initialize ? this.initialize.apply(this, args) || this : this;' +
													'};'
									)(toArr);
							} catch (e) {
									/* eslint-disable no-empty */
							}
					}
					inherits(ctor, parent);
					ctor.prototype.constructor = ctor;
					ctor.extend = function(methods, statics) {
							return makeClass(ctor, methods, statics);
					};
					ctor.inherits = function(Class) {
							inherits(ctor, Class);
					};
					ctor.methods = function(methods) {
							extend(ctor.prototype, methods);
							return ctor;
					};
					ctor.statics = function(statics) {
							extend(ctor, statics);
							return ctor;
					};
					ctor.methods(methods).statics(statics);
					return ctor;
			}
			var Base = (exports.Base = makeClass(Object, {
					className: 'Base',
					callSuper: function(parent, name, args) {
							var superMethod = parent.prototype[name];
							return superMethod.apply(this, args);
					},
					toString: function() {
							return this.constructor.name;
					}
			}));
			return exports;
	})({});
	var partial = _.partial = (function (exports) {
			/* Partially apply a function by filling in given arguments.
			 *
			 * |Name       |Desc                                    |
			 * |-----------|----------------------------------------|
			 * |fn         |Function to partially apply arguments to|
			 * |...partials|Arguments to be partially applied       |
			 * |return     |New partially applied function          |
			 */
			/* example
			 * const sub5 = partial(function(a, b) {
			 *     return b - a;
			 * }, 5);
			 * sub5(20); // -> 15
			 */
			exports = restArgs(function(fn, partials) {
					return function() {
							var args = [];
							args = args.concat(partials);
							args = args.concat(toArr(arguments));
							return fn.apply(this, args);
					};
			});
			return exports;
	})({});
	var once = _.once = (function (exports) {
			/* Create a function that invokes once.
			 *
			 * |Name  |Desc                   |
			 * |------|-----------------------|
			 * |fn    |Function to restrict   |
			 * |return|New restricted function|
			 */
			/* example
			 * function init() {}
			 * const initOnce = once(init);
			 * initOnce();
			 * initOnce(); // -> init is invoked once
			 */
			exports = partial(before, 2);
			return exports;
	})({});
	var Emitter = _.Emitter = (function (exports) {
			/* Event emitter class which provides observer pattern.
			 *
			 * ### on
			 *
			 * Bind event.
			 *
			 * ### off
			 *
			 * Unbind event.
			 *
			 * ### once
			 *
			 * Bind event that trigger once.
			 *
			 * |Name    |Desc          |
			 * |--------|--------------|
			 * |event   |Event name    |
			 * |listener|Event listener|
			 *
			 * ### emit
			 *
			 * Emit event.
			 *
			 * |Name   |Desc                        |
			 * |-------|----------------------------|
			 * |event  |Event name                  |
			 * |...args|Arguments passed to listener|
			 *
			 * ### removeAllListeners
			 *
			 * Remove all listeners.
			 *
			 * |Name |Desc      |
			 * |-----|----------|
			 * |event|Event name|
			 *
			 * ### mixin
			 *
			 * [static] Mixin object class methods.
			 *
			 * |Name|Desc           |
			 * |----|---------------|
			 * |obj |Object to mixin|
			 */
			/* example
			 * const event = new Emitter();
			 * event.on('test', function(name) {
			 *     console.log(name);
			 * });
			 * event.emit('test', 'licia'); // Logs out 'licia'.
			 * Emitter.mixin({});
			 */
			exports = Class(
					{
							initialize: function Emitter() {
									this._events = this._events || {};
							},
							on: function(event, listener) {
									this._events[event] = this._events[event] || [];

									this._events[event].push(listener);

									return this;
							},
							off: function(event, listener) {
									var events = this._events;
									if (!has(events, event)) return;
									var idx = events[event].indexOf(listener);

									if (idx > -1) {
											events[event].splice(idx, 1);
									}

									return this;
							},
							once: function(event, listener) {
									this.on(event, once(listener));
									return this;
							},
							emit: function(event) {
									var _this = this;

									if (!has(this._events, event)) return;
									var args = slice(arguments, 1);
									var events = clone(this._events[event]);
									each(
											events,
											function(val) {
													return val.apply(_this, args);
											},
											this
									);
									return this;
							},
							removeAllListeners: function(event) {
									if (!event) {
											this._events = {};
									} else {
											delete this._events[event];
									}

									return this;
							}
					},
					{
							mixin: function(obj) {
									each(['on', 'off', 'once', 'emit'], function(val) {
											obj[val] = exports.prototype[val];
									});
									obj._events = obj._events || {};
							}
					}
			);
			return exports;
	})({});
	var MediaQuery = _.MediaQuery = (function (exports) {
			/* CSS media query listener.
			 *
			 * Extend from Emitter.
			 *
			 * ### constructor
			 *
			 * |Name |Desc       |
			 * |-----|-----------|
			 * |query|Media query|
			 *
			 * ### isMatch
			 *
			 * Return true if given media query matches.
			 *
			 * ### Events
			 *
			 * #### match
			 *
			 * Triggered when a media query matches.
			 *
			 * #### unmatch
			 *
			 * Opposite of match.
			 */
			/* example
			 * const mediaQuery = new MediaQuery('screen and (max-width:1000px)');
			 * mediaQuery.isMatch(); // -> false
			 * mediaQuery.on('match', () => {
			 *     // Do something...
			 * });
			 */
			exports = Emitter.extend({
					className: 'MediaQuery',
					initialize: function(query) {
							var _this = this;

							this.callSuper(Emitter, 'initialize');
							this._mql = window.matchMedia(query);

							this._mql.addListener(function() {
									_this.emit(_this.isMatch() ? 'match' : 'unmatch');
							});
					},
					isMatch: function() {
							return this._mql.matches;
					}
			});
			return exports;
	})({});
	_.isDarkMode = (function (exports) {
			/* Detect dark mode.
			 */
			/* example
			 * console.log(isDarkMode()); // true if dark mode
			 */
			var m = new MediaQuery('(prefers-color-scheme: dark)');
			exports = function() {
					return m.isMatch();
			};
			return exports;
	})({});
	var rtrim = _.rtrim = (function (exports) {
			/* Remove chars or white-spaces from end of string.
			 *
			 * |Name  |Desc              |
			 * |------|------------------|
			 * |str   |String to trim    |
			 * |chars |Characters to trim|
			 * |return|Trimmed string    |
			 */
			/* example
			 * rtrim(' abc  '); // -> ' abc'
			 * rtrim('_abc_', '_'); // -> '_abc'
			 * rtrim('_abc_', ['c', '_']); // -> '_ab'
			 */
			var regSpace = /\s+$/;
			exports = function(str, chars) {
					if (chars == null) return str.replace(regSpace, '');
					var end = str.length - 1;
					var charLen = chars.length;
					var found = true;
					var i;
					var c;
					while (found && end >= 0) {
							found = false;
							i = -1;
							c = str.charAt(end);
							while (++i < charLen) {
									if (c === chars[i]) {
											found = true;
											end--;
											break;
									}
							}
					}
					return end >= 0 ? str.substring(0, end + 1) : '';
			};
			return exports;
	})({});
	var trim = _.trim = (function (exports) {
			/* Remove chars or white-spaces from beginning end of string.
			 *
			 * |Name  |Desc              |
			 * |------|------------------|
			 * |str   |String to trim    |
			 * |chars |Characters to trim|
			 * |return|Trimmed string    |
			 */
			/* example
			 * trim(' abc  '); // -> 'abc'
			 * trim('_abc_', '_'); // -> 'abc'
			 * trim('_abc_', ['a', 'c', '_']); // -> 'b'
			 */
			var regSpace = /^\s+|\s+$/g;
			exports = function(str, chars) {
					if (chars == null) return str.replace(regSpace, '');
					return ltrim(rtrim(str, chars), chars);
			};
			return exports;
	})({});
	_.isDataUrl = (function (exports) {
			/* Check if a string is a valid data url.
			 *
			 * |Name  |Desc                        |
			 * |------|----------------------------|
			 * |str   |String to check             |
			 * |return|True if string is a data url|
			 */
			/* example
			 * isDataUrl('http://eustia.liriliri.io'); // -> false
			 * isDataUrl('data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D'); // -> true
			 */
			exports = function(str) {
					return regDataUrl.test(trim(str));
			}; // https://tools.ietf.org/html/rfc2397
			var regDataUrl = /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z0-9-.!#$%*+.{}|~`]+=[a-z0-9-.!#$%*+.{}|~`]+)*)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*?)$/i;
			return exports;
	})({});
	//输出组件接口
	exports('tools',_);
})